package com.mmall.practice.example.jvm;

/**
 * VM Options:
 * -verbose:gc -Xms20M -Xmx20M -Xmn10M -XX:+PrintGCDetails -XX:SurvivorRatio=8
 */

/*

对象的创建

1.当虚拟机收到一条new指令时，首先去检查这个指令的参数能否在常量池中定位到对应的符号引用，并且检查符号引用代表的类是否加载过、解析和初始化过，没有则进行对应的类加载过程。

2.在类检查通过后，虚拟机为新生对象从Java堆中分配内存。而内存的分配又有两种方式。

一种是指针碰撞，就是把空闲和正在使用的内存中间放一个指针隔开，所以这种方式实际就是把指针进行移动，当内存出现相互交错时。该方式自然就行不通了；

另一种方式是空闲列表，由虚拟机维护一个列表，分配内存后就更新这个列表的记录。至于使用哪种方式就要看是基于何种垃圾回收器而言。

除了怎么划分可用空间之外，还需要考虑虚拟机分配内存的频率，分配频率就会涉及到并发中的一些问题了。

JVM采用CAS（比较并交换）方式进行失败重试保证操作的原子性；另一种是每个线程在Java堆中预先分配一小块内存，也就是本地线程分配缓冲(TLAB)

3.内存分配完成后，虚拟机将分配到的内存空间都初始化为零值，使用TLAB，则可以提前到分配时进行。

4.虚拟机对对象进行必要的设置，也就是把该对象相关的信息存储在对象头之中,这些工作都完成后，一个新的对象已经产生了，接下来就是对象的初始化了。


对象的访问定位

对象的访问目前主流的方式有句柄和直接指针两种。

1.使用句柄访问，Java堆会划分出一块内存作为句柄池，对象的引用中存储的就是其句柄的地址，句柄包含了对象实例数据和类型数据的具体地址信息。

2.使用直接指针，堆就要考虑如何放置访问类型数据相关的信息，引用中存储的直接就是对象地址。

很显然，因为是直接指向地址，所以直接指针的方式更加快，但对象访问在Java中太过频繁，积少成多后也会造成较高的执行成本。
*/